package com.wsoft.utils.job;

import com.google.common.util.concurrent.ThreadFactoryBuilder;
import com.wsoft.config.JobConfig;
import com.wsoft.entity.TsJobEntity;
import com.wsoft.enums.JobStatusEnum;
import com.wsoft.handler.JobHandler;
import com.wsoft.query.job.JobListQuery;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.CollectionUtils;

import javax.annotation.PreDestroy;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.TimeUnit;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * 定时任务 作业启动类
 * @Author z001
 * @Date 2024/10/23 13:53
 */
@Slf4j
public class JobLauncher {

    private final JobRepository jobRepository;

    private final List<JobHandler> jobInterfaceList;


    public JobLauncher(JobConfig jobConfig,
                       JobRepository jobRepository,
                       List<JobHandler> jobInterfaceList) {
        this.jobRepository = jobRepository;
        this.jobInterfaceList = jobInterfaceList;

        // init job scheduler
        JobScheduler.init(jobConfig);

        // 任务自动检测配置 固定1个线程
        Integer initDelay = jobConfig.getInitDelay();
        Boolean refreshEnabled = jobConfig.getRefreshEnabled();
        Integer refreshInterval = jobConfig.getDbRefreshInterval();

        ThreadFactory factory = new ThreadFactoryBuilder().setNameFormat("JobLauncher-%d").build();
        ScheduledThreadPoolExecutor executor = new ScheduledThreadPoolExecutor(1, factory);


        Runnable launcherRunnable = () -> {
            try {
                // 查询所有任务
                List<TsJobEntity> jobList = this.queryJob();
                this.startOrRefreshJob(jobList);
            } catch (Throwable t) {
                log.error("Job Error:", t);
            }
            // 只在启动时 执行一次
            if (!refreshEnabled) {
                executor.shutdown();
            }
        };
        executor.scheduleWithFixedDelay(launcherRunnable, initDelay, refreshInterval, TimeUnit.SECONDS);
    }

    /**
     * 查询数据库
     * 启动/刷新任务
     */
    public void startOrRefreshJob(List<TsJobEntity> jobList) {
        // 查询任务配置
        if (CollectionUtils.isEmpty(jobList) || CollectionUtils.isEmpty(jobInterfaceList)) {
            //任务列表为空
            return;
        }

        // 任务实现类
        Map<String, JobHandler> jobImplMap = jobInterfaceList.stream().collect(Collectors.toMap(JobHandler::getClassName, Function.identity()));
        for (TsJobEntity jobEntity : jobList) {
            //添加单个任务
            addJob(jobImplMap,jobEntity);
        }
    }

    /**
     * 添加单个任务
     * @param jobImplMap
     * @param jobEntity
     */
    public void addJob(Map<String, JobHandler> jobImplMap, TsJobEntity jobEntity ){
        // 查找任务实现类
        JobHandler jobImpl = jobImplMap.get(jobEntity.getClassPath());
        if (null == jobImpl) {
            return;
        }
        //todo
        JobExecutor jobExecute = new JobExecutor(jobEntity,jobImpl,jobRepository);
        JobScheduler.addJob(jobExecute);
    }


    /**
     * 查询全部任务
     *
     * @return
     */
    private List<TsJobEntity> queryJob() {
        JobListQuery jobListQuery = new JobListQuery();
        jobListQuery.setStatus(JobStatusEnum.START.getType());
        return jobRepository.getJobManager().listJob(jobListQuery);
    }


    @PreDestroy
    public void destroy() {
        JobScheduler.destroy();
        log.info("==== wsoft-ass ==== destroy job");
    }
}
